﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
// State object for reading client data asynchronously    
//c＃中的类的实例都是引用类型，用简单的赋值运算符“＝”无法创建它的副本
namespace Pixcom
{
    /************************
    * 定义圖片分辨率枚举定义
    * ****************/
    public enum RESOLUTION {
        _160x120=0,
        _320x340=1,
        _640x480=2,
        _800x600=3,
        _1024x768=4,
        _1280x960=5,
        _1600x1200=6,
        _2048x1536=7,
        _2592x1944=8
    }

    /************************
    * 定义圖片质量枚举定义
    * ****************/
    public enum IMGQUANLITY
    {
        SUPERHIGH=1,
        HIGH=2,
        MID=3,
        LOW=4
    }
    /************************
   * 定义圖片格式枚举定义
   * ****************/
    public enum IMGFORMAT
    {
         JPG=1,
         RGB565=2,
         YUV422=3,
         GRAY=4
    }
    /************************
 * 定义聚焦枚举定义
 * ****************/
    public enum EXPOSURE
    {
        AUTO=0,
        MANUAL=0x80
    }
    /************************
 * 定义顔色模式
 * ****************/
    public enum COLORMODE
    {
        COLOR = 0x00,
        GRAY = 0x10
    }
    /************************
    * 定义對焦模式
    * ****************/
    public enum FOCUSEMODE
    {
        AUTO = 0X01,
        READ = 0X02,
        MANUAL=0X03
    }

    /************************
     * 定义圖片參數
     * ****************/
    public struct ImgParam
    {
        public byte resolution; //分辨率
        public byte quanlity;//圖片質量
        public byte colorable;//0 彩色 1 黑白
        public byte format;//图片格式 1 JPG 2 RGB565 3 YUV422 4 8位灰度模式  ，本程序支持  1 4 模式
        public byte exposure;//曝光 BIT T=0 BIT6!0 =0自动曝光 ，BIT7=1 BIT6~4=0 BIT3~0 为曝光值
        public byte exposureVal;//曝光值
        public byte focuseVal;//聚焦值
        public byte focuseMode;//    
    };
    /************************
  * 定义图片类数据结构
  * ****************/
    public struct stImagine
    {
        public int ImgLen;//当前图像长度 byte
        public int ImgTotLen;//图像总长度 byte
        public byte[] ImgBuf; //多帧图像
        public int[] ImgLenArr;//
        public int[] ImgPktArr;//
        public Image[] ImagineArr;//
        public int ImgInx;//
        public int ImgTotNum;//
        public int PktInx; //当询问的图像数据包 索引
        public int Pktsz; //当前图像数据总 包数 
        public int ImgShowCnt;//
        public int VCM; //焦距
        public string AutoSaveFN;//自动保存
    };

    /************************
     * 定义串口类数据结构
     * ****************/
    public struct stSPort
    {
        public int RcvCnt;
        public int RcvMark;
        public int Timeup;
        public bool RcvBgn;
        public bool ForceStop;
        public bool Open;
        public int PKTsz;
        public byte[] SndBuf;
        public byte[] ConstShotCMD;
        public byte[] RS_RcvBuf;// = new byte[SP_INBUFFER_MAX_SIZE];
    };

    /************************
     * 定义指令超时类数据结构
     * ****************/
    public struct stCMDOVT
    {
        public int Timer;
        public int Threshold;
        public int ReSendCnt;
        public int TotReSend;
    };
    //回调的消息内容
    public enum SOCKET_STAT
    {
        WaitConnect = 0,
        NewConnect = 1,
        IdentifyEquip = 2,
        RecvMsg = 3,
        DisConn = 4,
        UnListened = 5,
        SendMsg = 6,
        ERR = 7,
        Package = 8,
        SendOK=9,
        Unknow  　//成员的值可以设置成一样的，但是成员不行
    }
    public class ImageObject {
        public stImagine stImg;
        public stSPort stSP;
        public stCMDOVT stOVT;
        public ImgParam imgParam;
        public ImageObject(int addr)
        {
            eqpid = (byte)addr;

            stSP.RcvCnt = 0;
            stSP.Timeup = 0;
            stSP.RcvBgn = false;
            stSP.Open = false;
            stSP.ForceStop = false;
            stSP.SndBuf = new byte[16];
            stSP.ConstShotCMD = new byte[16];

            stSP.RS_RcvBuf = new byte[PicProtocal.SP_INBUFFER_MAX_SIZE];
            stSP.PKTsz = 2048;

            //stImg.ImgBuf = new byte[3600000];
            //arr用於多拍的參數統計
            stImg.ImgLenArr = new int[20];
            stImg.ImgPktArr = new int[20];
            stImg.ImagineArr = new Image[20];

            stImg.ImgLen = 0;
            stImg.ImgInx = 0;
            stImg.ImgShowCnt = 0;
            stImg.PktInx = 0;

            imgParam.resolution =(byte) RESOLUTION._2048x1536;
            imgParam.format = (byte)IMGFORMAT.JPG;
            imgParam.quanlity = (byte)IMGQUANLITY.HIGH;
            imgParam.colorable = (byte)COLORMODE.COLOR;
            imgParam.exposure = (byte)EXPOSURE.AUTO;
            imgParam.focuseMode = (byte)FOCUSEMODE.AUTO;
            PackageTickRate = 2;// PicProtocal.LinkHeartRate / 2;
            
            Logger.Debug("==========================新建ADDR=【{0}】",addr);
        }
        public bool OnLine = false;
        //当前缓冲器中的数据长度
        public int PackageLen = 0;
        // 数据包缓存，所有接受数据的缓存，FIFO，移除已经解析的数据.     
        public byte[] Package = new byte[PicProtocal.BUF_SIZE];

        //当前缓冲器中的数据长度
        public int BUFLen = 0;
        // 数据包缓存，所有接受数据的缓存，FIFO，移除已经解析的数据.     
        public byte[] BUF = new byte[PicProtocal.BUF_SIZE];
        ////当前接收的数据长度
        //public int bytesRead = 0;
        //// 当前接受的数据.     
        //public byte[] bufRead = new byte[PicProtocal.BUF_SIZE];

        //当前接收的数据长度
        public int bytesSend = 0;
        // 当前接受的数据.     
        public byte[] bufsend = new byte[PicProtocal.BUF_SIZE];
        //当前正在进行采集的图片路径
        public string dir="E:\\DodemPicture\\";

        public string filename = "default.jpg";
        //当前正在进行采集的图片路径
        public string path;

        //采集完成,用於界面或是其他對該值進行檢測判斷  packagetype 是狀態量是變化的
        public bool ImageOK = false;

        //设备的地址 0~255
        public byte eqpid =255;
        //设备名称
        public byte eqpname = 0;
        //當前接收到的數據包的類型

        public byte PackageType = 0;
        //當前的心跳值
        public int PackageTick;
        //數據包的響應頻率 應該為連接頻率的 2/3 保障 socke連接
        public int DefaultTickRate;
        //心跳率
        public int PackageTickRate;

        public void PackageOn() {
            PackageTick =  PackageTickRate;
        }

        /*
          数据接收是否超时  数据包正常 返回 true
        */
        public bool CheckPackageOn() {
            PackageTick--;
            bool result = true;
            if (PackageTick <0)
            {
                Logger.Info("设备【{0}】数据包超时！",eqpid);
                result = false;
            }
             
            return result;

        }
        //當前是否有未完成的拍圖 行爲，ture 有 false 沒得 抓圖的時候直接設置 stImg.Pktsz 為1 傳圖成功會自動更行為圖片實際包數量
        public bool isPictureing() {

            return (stImg.PktInx < stImg.Pktsz)&&(stImg.Pktsz>0);
        }

        //是否完整數據包
        public void CheckPackage()
        {
            //解析报文
            PackageOn();

            String result = PicProtocal.RS_RcvHandler(this);
            Logger.Info(result);
           
        }

    }
   


    public class SocketObject:IDisposable
    {
        public String[] statDesc = {
            "链接数量{0}",
            "新链接[{0}]：-{1}",
            "设备地址[{0}]：{1}" ,
            "接收消息[{0}][{1}]：{2}",
            "断开链接[{0}]:{1}",
            "退出监听！",
            "发送消息[{0}][{1}]：{2}",
           
            "错误：{0}",
            "数据包[{0}]",
            "发送成功{0}{1}",
            "未知状态！" };
        //当前对象是否监听服务
        public bool isServer = false;
        //作为服务当前客户端的数量
        public int socketCount = 0;

        public bool OnLine = false;

        //链接的索引号
        public int index = 0;
        public int addr = 255;


        //当前链接是新的 用于更新状态时使用
        public bool isNew = true;

        public SOCKET_STAT stat = SOCKET_STAT.Unknow;
        // Client socket.     
        public Socket workSocket = null;

        //客户端信息
        public String soketInfo = "";

        //当前缓冲器中的数据长度
        public int BUFLen = 0;
        // 数据包缓存，所有接受数据的缓存，FIFO，移除已经解析的数据.     
        public byte[] BUF = new byte[PicProtocal.BUF_SIZE];
        //当前接收的数据长度
        public int bytesRead = 0;
        // 当前接受的数据.     
        public byte[] bufRead = new byte[PicProtocal.BUF_SIZE];
        public String errStr = "";

        //心跳 ，socket 收到数据 设置该值到 HeartValue
        public int HeartRate { get; set; } 
        public void HeartOn() {
            HeartValue = HeartRate;
           
            Logger.Info("心跳... ...{2}=={0},{1},【{3}】", HeartValue,HeartRate, soketInfo,sb);
        }

        public bool CheckHeart() {
            bool result = true;
            HeartValue--;
            if (HeartValue < 0) {
                Logger.Info("接收数据超时，主动断开链接！");
                Close();
                result = false; 
            }
            return result;
        }
        

       
        //当前心跳值, 在 server 线程中 减少该值，判断是否大于0，否则 心跳超时 判断为断开连接
        public int HeartValue;

        // Received data string.     
        public String sb;


        //BitConverter转换
        public SocketObject(Socket ws, SOCKET_STAT st) {
            sb = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff");
            workSocket = ws;
            stat = st;
            HeartRate = PicProtocal.LinkHeartRate;
 
            try
            {
                soketInfo = workSocket != null ? workSocket.RemoteEndPoint.ToString() : "";
            }
            catch (Exception e)
            {

                Logger.Error(e.ToString());
            }
        }
        
        public String clientInfo() {
            String desc = statDesc[(int)stat];

            if (stat == SOCKET_STAT.WaitConnect) {
                desc = String.Format(desc, socketCount);
            }
            else if (stat == SOCKET_STAT.NewConnect)
            {
                desc = String.Format(desc, index,soketInfo);
            }
            else if (stat == SOCKET_STAT.IdentifyEquip)
            {
                desc = String.Format(desc, index, addr);
            }
            else if (stat == SOCKET_STAT.RecvMsg)
            {
                desc = String.Format(desc, index,bytesRead,PicProtocal.byteToHexStr(bufRead, 0,bytesRead));
            }
            else if (stat == SOCKET_STAT.DisConn)
            {
                desc = String.Format(desc, index, soketInfo );

            }
            else if (stat == SOCKET_STAT.UnListened)
            {
                desc = String.Format(desc);
            }
            //else if (stat == SOCKET_STAT.SendMsg)
            //{
            //    desc = String.Format(desc, index, bytesSend, PicProtocal.byteToHexStr(bufsend, 0,bytesSend));
            //}
            else if (stat == SOCKET_STAT.ERR)
            {
                desc = String.Format(desc,errStr);
            }
            else if (stat == SOCKET_STAT.Package)
            {
                desc = String.Format(desc, addr);
            }
            else if (stat == SOCKET_STAT.SendOK)
            {
                desc = String.Format(desc, soketInfo);
            }
            else if (stat == SOCKET_STAT.Unknow)
            {
                desc = String.Format(desc);
            }

            return desc;// String.Format("状态{0}!", stat);

        }
         
        public void GetEquiptInfo() {

            Byte[] sendbyf = PicProtocal.RS_PacketTx(0xff, PicProtocal.RSCMD_ASK_PARA, 0);
            Write(sendbyf, 0, sendbyf.Length);

        }

        private void Write(byte[] data, int offset, int len)
        {
            try
            {
                // Begin sending the data to the remote device.     
                if (workSocket != null)
                {
                    Logger.Debug("发送数据S：{0},【{3}】,[{1}],{2}", workSocket.RemoteEndPoint.ToString(), len, PicProtocal.byteToHexStr(data, offset, len), sb);
                    workSocket.Send(data, offset, len, SocketFlags.None);

            }
                else {
                Logger.Error("发送失败，連接已經關閉");
            }

        }
            catch (Exception e)
            {

                Logger.Error("发送失败：{0}", e.ToString());
                Close();

                //UpdateAsyncInfo(state);
            }

        }

        //指定设备地址进行发送,可以发送广播命令给所有设备
        //也可以根据报文中的设备 地址 来检验发送，但是那样不够灵活
        public void Send(  byte[] data,int offset,int len)
        {
         
            Write(data,offset,len);
            
        }

        public void Send(byte[] data)
        {
            BUFLen = 0;//清空之前的数据
            Send(data, 0, data.Length);
        }

        public void Close()
        {
            OnLine = false;
            stat = SOCKET_STAT.DisConn;
            Logger.Info("断开链接addr=【{0}】,Info=【{1}】", addr,soketInfo);



            try
            {
                if(workSocket!=null)
                {
                    workSocket.Shutdown(SocketShutdown.Both);
                    workSocket.Close();//断开之前的链接   
                }
              


            }
            catch (Exception e)
            {
                Logger.Error(e.ToString());

            }
            finally {
                 
            }
            //  Dispose();
            workSocket = null;



        }

        public void Dispose()
        {

            //try
            //{
            //    ((IDisposable)workSocket).Dispose();
            //}
            //catch (Exception)
            //{


            //}
            //finally
            //{

            //}

            Logger.Info("销毁socketobject{0}",sb);

        }
    }
    public class AsynchronousSocketListener
    {
        SynchronizationContext m_SyncContext = null;
        private bool isExit=false;
        private bool isExit1 = false;
        private Hashtable clientTable = new Hashtable();//当前socket链接的 地址和soket的对应
        private Hashtable imgObjTable = new Hashtable();//地址和 imageobj的对应
        private SendOrPostCallback cb;
        private delegate void beginInvokeCB();
        // Thread signal.     
        public static ManualResetEvent allDone = new ManualResetEvent(false);
      

        public AsynchronousSocketListener(SendOrPostCallback callback)
        {
            cb = callback;
            //获取UI线程同步上下文
            m_SyncContext = SynchronizationContext.Current;
            //Control.CheckForIllegalCrossThreadCalls = false;

            try
            {
               
                new Task(() =>
                {
                    while (isExit1 == false)
                    {
                        Thread.Sleep(1000 * 10);//心跳周期 10s
                     //   Logger.Info("當前客戶段數量====T={0} ", clientTable.Count );
                        Logger.Info("當前客戶段數量====T={0},K={1},V={2}", clientTable.Count, clientTable.Keys.Count, clientTable.Values.Count);
                        foreach (ImageObject imgobj in imgObjTable.Values)
                        {
                            //检查心跳
                            Logger.Info("當前客戶段數量====addr={0},path={1}", imgobj.eqpid, imgobj.path);

                            SocketObject skobj = getSocket(imgobj.eqpid.ToString());
                            if (skobj != null)
                            {
                                
                                if (!imgobj.CheckPackageOn()) {

                                    if (imgobj.isPictureing())
                                    {
                                        Logger.Info("有抓拍任务，重复执行！");

                                        skobj.Send(imgobj.bufsend);

                                    }
                                    else {
                                        skobj.GetEquiptInfo();
                                    }
                              }
                                if (skobj.CheckHeart()) {
                                    imgobj.OnLine = false;
                                }

 
                            }
 

                        }
                    }
                    Logger.Info("退出任务》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》");
                }).Start();

            }
            catch (Exception e)
            {

                Logger.Error("TASK运行出错{0}",e.ToString());
            }



        }


        private void UpdateAsyncInfo(ImageObject imgobj) {

            m_SyncContext.Post(cb, imgobj);
        }


        public ImageObject getImgObj(String eqpid)
        {
            ImageObject imgobj = null;


            if (imgObjTable.ContainsKey(eqpid))
            {
                imgobj = imgObjTable[eqpid] as ImageObject;

                Logger.Info("找到地址为【{0}】的imgobj={1}", eqpid, imgobj);
            }
            else
            {
                Logger.Error("没有找到地址为【{0}】，的imgobj", eqpid);
            }
            return imgobj;
        }


        public SocketObject getSocket(String eqpid) {
            SocketObject sketobj = null;


            if (clientTable.ContainsKey(eqpid))
            {
                sketobj = clientTable[eqpid] as SocketObject;
                Logger.Info("找到地址为【{0}】的socket，{1}",eqpid, sketobj.soketInfo);
            }
            else {
                Logger.Error("没有找到地址为【{0}】，的socket连接", eqpid);
            }
            return sketobj;
        }
 

        public void StartListening()
        {
            ThreadStart ts = new ThreadStart(AcceptConnect);
            Thread myThread = new Thread(ts);
            myThread.Start();
        }


        public ImageObject UpdateClientHashTable(SocketObject sktobj,int adr,byte[] package,int packagelen) {

            String addr = adr.ToString();
            //不存在链接 添加
            if (!clientTable.Contains(addr))
            {
                clientTable.Add(addr, sktobj);
            }
            else {
                
                SocketObject obj = clientTable[addr] as SocketObject;
                //存在 判断链接是否发生变化
                if (!sktobj.Equals(obj))
                {
                    Logger.Info("更新addr=【{0}】的链接为【{1}】", addr, sktobj.soketInfo);
                    clientTable.Remove(addr);
                    obj.Close();

                    sktobj.addr = adr;
                
                    //clientTable[addr] = sktobj;
                    clientTable.Add(addr, sktobj);


                }
                else {

                }
              
            }
            //判断存在设备数据对象 ，不存在 添加，存在更新 数据包
            if (!imgObjTable.Contains(addr)) {
                imgObjTable.Add(addr, new ImageObject(adr));
            }
            ImageObject imgobj = imgObjTable[addr] as ImageObject;
            imgobj.Package = package;
            imgobj.PackageLen = packagelen;
            imgobj.OnLine = true;
            //解析数据包
            imgobj.CheckPackage();
            return imgobj;

        }


        public void stop() {
            isExit1 = true;
            isExit = true;
            allDone.Set();
        }
        public void AcceptConnect() { 
            // Data buffer for incoming data.     
            byte[] bytes = new Byte[1024];
            // Establish the local endpoint for the socket.  
            uint dummy = 0;
            byte[] inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
            uint time = 1000*5;
            BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
            BitConverter.GetBytes(time).CopyTo(inOptionValues, Marshal.SizeOf(dummy));//多长时间
            BitConverter.GetBytes(time).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);//间隔 MS
            //byte[] inValue = new byte[] { 1, 0, 0, 0, 0x20, 0x4e, 0, 0, 0xd0, 0x07, 0, 0 };// 首次探测时间20 秒, 间隔侦测时间2 秒
            // The DNS name of the computer     
            // running the listener is "host.contoso.com".     
            //IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
            //IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
          //   IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 51015);
            // Create a TCP/IP socket.     
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     
            //clientList.Add(serverSoket);
       
            try
            {

                listener.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
                listener.Bind(localEndPoint);
                listener.Listen(100);//设定最多100个排队连接请求
               
                //就是用tcpclient.Close(); 就行了。 断开连接
                //(1)Rset方法：将事件状态设为非终止状态，导致线程阻塞。这里的线程阻塞是指允许其他需要等待的线程进行阻塞即让含WaitOne()方法的线程阻塞；
                //(2)Set方法：将事件状态设为终止状态，允许一个或多个等待线程继续。该方法发送一个信号给操作系统，让处于等待的某个线程从阻塞状态转换为继续运行，即WaitOne方法的线程不在阻塞；
                //(3)WaitOne方法：阻塞当前线程，直到当前的等待句柄收到信号。此方法将一直使本线程处于阻塞状态直到收到信号为止，即当其他非阻塞进程调用set方法时可以继续执行。
                while (isExit==false)
                {
                    // Set the event to nonsignaled state.     
                    allDone.Reset();
                  
                    // Start an asynchronous socket to listen for connections.     
                    Logger.Info("开始监听...");
                  
                    listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                    //   MessageBox.Show("IAsyncResult", "", MessageBoxButtons.OK);
               
                    // Wait until a connection is made before continuing.     
                    allDone.WaitOne();
                   
                }

 
                listener.Close();
            }
            catch (Exception e)
            {
                Logger.Error("监听异常，退出监听！"+e.ToString());
       
                listener.Close();
            }
       
            Logger.Info("退出监听！");

        }
        public   void AcceptCallback(IAsyncResult ar)
        {
            // Signal the main thread to continue.     
            allDone.Set();
            // Get the socket that handles the client request.    
            Socket listener = (Socket)ar.AsyncState;
            try
            {
            
                //需要添加异常处理，listener 关闭了 
                Socket handler = listener.EndAccept(ar);

                // Create the state object.     
                SocketObject state = new SocketObject(handler, SOCKET_STAT.NewConnect);

                Logger.Info("新建连接:{0}" , handler.RemoteEndPoint.ToString());

                handler.BeginReceive(state.bufRead, 0, PicProtocal.BUF_SIZE, 0, new AsyncCallback(ReadCallback), state);

                state.GetEquiptInfo();
                

              

                // 添加到 未知设备列表，设备名称 未知
            }
            catch (Exception e)
            {

                Logger.Error("建立连接，绑定readcallback失败{0}",e.ToString());
          
                
            }

        }
        public   void ReadCallback(IAsyncResult ar)
        {
            String content = String.Empty;
            // Retrieve the state object and the handler socket     
            // from the asynchronous state object.     
            SocketObject state = (SocketObject)ar.AsyncState;
            try
            {
               
                Socket handler = state.workSocket;
           
                // Read data from the client socket.  
                //接收数据的时候 在这 可能出现 远程主机强制关闭连接，导致这里读数据出错的情况，需要进行异常处理   
                if (handler == null)
                {
                    Logger.Info("连接已经失效[{0}]",state.addr,state.workSocket.RemoteEndPoint.ToString());
                    return;
                }
                    
                state.bytesRead = handler.EndReceive(ar);

                if (state.bytesRead > 0)
                {
                    state.HeartOn();//更新 心跳
                    Logger.Debug("接收数据：{0},【{3}】，[{1}],{2}", handler.RemoteEndPoint.ToString(), state.bytesRead, PicProtocal.byteToHexStr(state.bufRead, 0, state.bytesRead),state.sb);

                    if ((state.BUFLen + state.bytesRead) >PicProtocal.BUF_SIZE)
                        state.BUFLen = 0;

                    Array.Copy(state.bufRead, 0, state.BUF, state.BUFLen, state.bytesRead);
                    state.BUFLen += state.bytesRead;

                    byte[] package =new byte[1];
                    int packagelen = 0;
                    int addr = 255;

                   if( PicProtocal.ParsePackage(ref state.BUF, ref state.BUFLen, ref addr,ref packagelen, ref package))
                    {

                        Logger.Info("收到完整数据包！=====================================================\n{0}\n\n", PicProtocal.byteToHexStr(state.BUF, 0, state.BUFLen));
                        ImageObject imgobj = UpdateClientHashTable(state, addr, package, packagelen);
                        state.stat = SOCKET_STAT.Package;
                       
 
                        //拍照成功 开始读取图像，讀取過程種 讀取圖像 
                        if (imgobj.isPictureing())
                        {
                            state.Send(imgobj.bufsend, 0, imgobj.bytesSend);

                        }
                        //如果是參數詢問完畢 查看上一次的圖像是否 讀取完畢
                        else if (imgobj.PackageType == PicProtocal.RSACK_ASK_PARA)
                        {

                            //设备地址不是255 表示该设备以及被识别了  ,如果已经有该地址的链接存在替换socket 链接
                           
                            state.stat = SOCKET_STAT.IdentifyEquip;
                            state.OnLine = true;
                         
                            byte[] send = PicProtocal.single_short(imgobj);
                            state.Send(send);

                           
                        }
                        UpdateAsyncInfo(imgobj);
                    }
                    
                   
                    //清空数据，重新开始异步接收 
                    state.bufRead = new byte[PicProtocal.BUF_SIZE];
 

                        try
                        {
                            // 重新开始异步接收 
                            handler.BeginReceive(state.bufRead, 0, PicProtocal.BUF_SIZE, 0, new AsyncCallback(ReadCallback), state);
                        }
                        catch (Exception)
                        {

                            Logger.Error("重新接收数据出错！");
                        }
                  
    
                }

            }
            catch (Exception e)
            {
                Logger.Error("读取数据出错，被动关闭连接{0}，{1}", state.soketInfo, e.ToString());
            
                state.Close();


            }
        }

        public void Send(int addr, byte[] buf, int offset, int len) {
            SocketObject obj = getSocket(addr.ToString());
            if (obj != null)
            {
                obj.Send(buf, offset, len);
            }
            else {
                Logger.Error("获取有效链接失败【{0}】，不能发送数据",addr);
            }
        }
      

        
    }
}